home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
UNIXLIB37B
/
!UnixLib37
/
src
/
c
/
system
< prev
next >
Wrap
Text File
|
1996-11-09
|
4KB
|
141 lines
/****************************************************************************
*
* $Source: /unixb/home/unixlib/source/unixlib37/src/c/RCS/system,v $
* $Date: 1996/10/30 21:58:59 $
* $Revision: 1.4 $
* $State: Rel $
* $Author: unixlib $
*
* $Log: system,v $
* Revision 1.4 1996/10/30 21:58:59 unixlib
* Massive changes made by Nick Burret and Peter Burwood.
*
* Revision 1.3 1996/09/16 21:23:52 unixlib
* CL_0002 Nick Burret
* Minor changes to file handling
* Change most error numbers, and use in assembler sources (SJC)
* Various minor bug fixes and compatability changes.
*
* Revision 1.2 1996/05/06 09:03:13 unixlib
* Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
* Saved for 3.7a release.
*
* Revision 1.1 1996/04/19 21:26:42 simon
* Initial revision
*
***************************************************************************/
static const char rcs_id[] = "$Id: system,v 1.4 1996/10/30 21:58:59 unixlib Rel $";
/* c.system: Written by Nick Burrett, 6 October 1996. */
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
/* Execute LINE as a shell command, returning its status. */
int system (const char *line)
{
int status, save;
pid_t pid;
struct sigaction sa, intr, quit;
sigset_t block, omask;
if (line == NULL)
return 1;
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigemptyset (&sa.sa_mask);
/* Ignore signals SIGINT and SIGQUIT. */
if (sigaction (SIGINT, &sa, &intr))
return -1;
if (sigaction (SIGQUIT, &sa, &quit))
{
/* Bit of an error, restore SIGINT and preserve the errno. */
save = errno;
(void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
errno = save;
return -1;
}
/* Block SIGCHLD. */
sigemptyset (&block);
sigaddset (&block, SIGCHLD);
save = errno;
if (sigprocmask (SIG_BLOCK, &block, &omask))
{
if (errno == ENOSYS)
errno = save;
else
{
/* Awkward error, so restore signal handlers and return. */
save = errno;
(void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
(void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
errno = save;
return -1;
}
}
/* vfork the process. */
pid = vfork ();
if (pid == (pid_t) 0)
{
char *shell, *path;
/* Restore the signals. */
sigaction (SIGINT, &intr, (struct sigaction *) NULL);
sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
/* Could deliver a few pending signals here. */
sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
/* Execute the shell. */
if (!(path = getenv ("SHELL")))
{
if (*line == '*')
execl ((char *) line, 0);
else
execl ("*", "", (char *) line, 0);
_exit (1);
}
shell = strrchr (path, '/');
if (shell)
shell++;
else
shell = path;
execl (path, shell, "-c", (char *)line, 0);
_exit (1);
}
else if (pid < (pid_t) 0)
/* The fork failed. */
status = -1;
else
if (waitpid (pid, &status, 0) != pid)
status = -1;
/* Got here on a vfork failure. So restore signals and the blocking
mask then exit. */
save = errno;
if ((sigaction (SIGINT, &intr, (struct sigaction *) NULL) |
sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) |
sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL)) != 0)
{
if (errno == ENOSYS)
errno = save;
else
return -1;
}
return status;
}